home *** CD-ROM | disk | FTP | other *** search
- /*
- * atari_scsi.c -- Device dependant functions for the Atari generic SCSI port
- *
- * Copyright 1994 Roman Hodek
- * EMail: rnhodek@cip.informatik.uni-erlangen.de (Internet)
- * or: Roman_Hodek@n.maus.de (MausNet, NO mail > 16 KB!)
- *
- * Loosely based on the work of Robert De Vries' team and added:
- * - working real DMA
- * - Falcon support (untested yet!) ++bjoern fixed and now it works
- * - lots of extensions and bug fixes.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
- *
- */
-
-
- /**************************************************************************/
- /* */
- /* Notes for Falcon SCSI: */
- /* ---------------------- */
- /* */
- /* Since the Falcon SCSI uses the ST-DMA chip, that is shared among */
- /* several device drivers, locking and unlocking the access to this */
- /* chip is required. But locking is not possible from an interrupt, */
- /* since it puts the process to sleep if the lock is not available. */
- /* This prevents "late" locking of the DMA chip, i.e. locking it just */
- /* before using it, since in case of disconnection-reconnection */
- /* commands, the DMA is started from the reselection interrupt. */
- /* */
- /* Two possible schemes for ST-DMA-locking would be: */
- /* 1) The lock is taken for each command separately and disconnecting */
- /* is forbidden (i.e. can_queue = 1). */
- /* 2) The DMA chip is locked when the first command comes in and */
- /* released when the last command is finished and all queues are */
- /* empty. */
- /* The first alternative would result in bad performance, since the */
- /* interleaving of commands would not be used. The second is unfair to */
- /* other drivers using the ST-DMA, because the queues will seldom be */
- /* totally empty if there is a lot of disk traffic. */
- /* */
- /* For this reasons I decided to employ a more elaborate scheme: */
- /* - First, we give up the lock everytime we can (for fairness), this */
- /* means every time a command finishes and there are no other commands */
- /* on the disconnected queue. */
- /* - If there are others waiting to lock the DMA chip, we stop */
- /* issueing commands, i.e. moving them onto the issue queue. */
- /* Because of that, the disconnected queue will run empty in a */
- /* while. Instead we go to sleep on a 'fairness_queue'. */
- /* - If the lock is released, all processes waiting on the fairness */
- /* queue will be woken. The first of them trys to re-lock the DMA, */
- /* the others wait for the first to finish this task. After that, */
- /* they can all run on and do their commands... */
- /* This sounds complicated (and it is it :-(), but it seems to be a */
- /* good compromise between fairness and performance: As long as noone */
- /* else wants to work with the ST-DMA chip, SCSI can go along as */
- /* usual. If now someone else comes, this behaviour is changed to a */
- /* "fairness mode": just already initiated commands are finished and */
- /* then the lock is released. The other one waiting will probably win */
- /* the race for locking the DMA, since it was waiting for longer. And */
- /* after it has finished, SCSI can go ahead again. Finally: I hope I */
- /* have not produced any deadlock possibilites! */
- /* */
- /**************************************************************************/
-
-
-
- #include <linux/config.h>
-
- #ifdef CONFIG_ATARI_SCSI
-
- /* #define NDEBUG (NDEBUG_DMA) */
-
- #define AUTOSENSE
- /* For the Atari version, use only polled IO or REAL_DMA */
- #define REAL_DMA
-
- #if I_HAVE_OVERRUNS == 1 || I_HAVE_OVERRUNS == 2
- #define READ_OVERRUNS
- #endif
-
- #include <linux/stddef.h>
- #include <linux/interrupt.h>
- #include <linux/bootinfo.h>
- #include <linux/atarihw.h>
- #include <linux/atariints.h>
- #include "../block/blk.h"
- #include "scsi.h"
- #include "hosts.h"
- #include "atari_scsi.h"
- #include "NCR5380.h"
- #include "constants.h"
- #include <linux/atari_stdma.h>
-
-
- #define IS_A_TT() (boot_info.bi_atari.model == ATARI_TT)
-
- #define SCSI_DMA_WRITE_P(elt,val) \
- __asm__ __volatile__ ( "movepl %0,%1@(0)" : : "d" (val), \
- "a" (&tt_scsi_dma.elt) );
-
- #define SCSI_DMA_READ_P(elt) ({ \
- unsigned long __val; \
- __asm__ __volatile__ ( "movepl %1@(0),%0" \
- : "=d" (__val) : "a" (&tt_scsi_dma.elt)); \
- __val; })
-
- #define SCSI_DMA_SETADR(adr) \
- do { \
- unsigned long __adr = (adr); \
- st_dma.dma_lo = (unsigned char)__adr; \
- __adr >>= 8; \
- st_dma.dma_md = (unsigned char)__adr; \
- __adr >>= 8; \
- st_dma.dma_hi = (unsigned char)__adr; \
- } while(0)
-
- #define SCSI_DMA_GETADR() ({ \
- unsigned long __adr; \
- __adr = st_dma.dma_lo; \
- __asm__ __volatile__ ("nop"); \
- __adr |= (st_dma.dma_md & 0xff) << 8; \
- __adr |= (st_dma.dma_hi & 0xff) << 16; \
- __adr; \
- })
-
-
-
- /***************************** Prototypes *****************************/
-
- static void scsi_dma_buserr( struct intframe *fp, void *data);
- static void scsi_tt_intr( struct intframe *fp, void *data);
- static void scsi_falcon_intr( struct intframe *fp, void *data);
- static void atari_scsi_fetch_restbytes( void );
- static void falcon_release_lock_if_possible( struct NCR5380_hostdata *
- hostdata );
- static void falcon_get_lock( void );
- static long atari_scsi_dma_residual( struct Scsi_Host *instance );
- static unsigned long atari_dma_xfer_len( unsigned long wanted_len );
- static unsigned char atari_scsi_tt_reg_read( unsigned char reg );
- static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value
- );
- static unsigned char atari_scsi_falcon_reg_read( unsigned char reg );
- static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char
- value );
-
- /************************* End of Prototypes **************************/
-
-
- static struct Scsi_Host *atari_scsi_host = NULL;
- static unsigned char (*atari_scsi_reg_read)( unsigned char reg );
- static void (*atari_scsi_reg_write)( unsigned char reg, unsigned char value );
-
- #ifdef REAL_DMA
- static unsigned long atari_dma_residual, atari_dma_startaddr;
- static short atari_dma_active;
- #endif
-
-
- #if defined(REAL_DMA)
-
- static void scsi_dma_buserr (struct intframe *fp, void *data)
-
- {
- if (tt_scsi_dma.dma_ctrl & 0x80) {
- printk( "SCSI DMA caused bus error near 0x%08lx\n",
- SCSI_DMA_READ_P( dma_addr_hi ));
- panic( "SCSI DMA bus error -- bad DMA programming!" );
- }
- else {
- /* Under normal circumstances we never should get to this point,
- * since both interrupts are triggered simultaneosly and the 5380
- * int has more priotity. When this irq is handled, that DMA
- * interrupt is cleared. So a warning message is printed here.
- */
- printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" );
- }
- }
-
- #endif
-
- #undef LOST_INTR
-
- #ifdef LOST_INTR
- extern volatile unsigned long intr_count;
- unsigned long curr_intr_count;
-
- #define CHECK_ICNT(pos) do { \
- if (intr_count != curr_intr_count) { \
- printk( "INTR_COUNT changed before " pos \
- ": curr_cnt=%lu intr_cnt=%lu\n", \
- curr_intr_count, intr_count ); \
- } \
- } while( 0 )
-
- #else
-
- #define CHECK_ICNT(pos)
-
- #endif
-
-
- static void scsi_tt_intr (struct intframe *fp, void *data)
-
- { int dma_stat;
- unsigned long flags;
- #ifdef LOST_INTR
- unsigned long prev_intr_count;
-
- prev_intr_count = curr_intr_count;
- curr_intr_count = intr_count;
- #endif
-
- #ifdef REAL_DMA
-
- dma_stat = tt_scsi_dma.dma_ctrl;
-
- #if (NDEBUG & NDEBUG_INTR)
- printk( "scsi%d: NCR5380 interupt, DMA status = %02x\n",
- atari_scsi_host->host_no, dma_stat & 0xff );
- #endif
-
- /* Look if it was the DMA that has interrupted: First possibility
- * is that a bus error occured...
- */
- if (dma_stat & 0x80) {
- printk( "SCSI DMA caused bus error near 0x%08lx\n",
- SCSI_DMA_READ_P( dma_addr_hi ));
- panic( "SCSI DMA bus error -- bad DMA programming!" );
- }
-
- /* If the DMA is active but not finished, we have the the case
- * that some other 5380 interrupt occured within the DMA transfer.
- * This means we have residual bytes, if the desired end address
- * is not yet reached. Maybe we have to fetch some bytes from the
- * rest data register, too. The residual must be calculated from
- * the address pointer, not the counter register, because only the
- * addr reg counts bytes not yet written and pending in the rest
- * data reg!
- */
- if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
- atari_dma_residual =
- ((struct NCR5380_hostdata *)(atari_scsi_host->hostdata))->dma_len -
- (SCSI_DMA_READ_P( dma_addr_hi ) - atari_dma_startaddr);
- #if (NDEBUG & NDEBUG_DMA)
- printk( "SCSI DMA: There are %ld residual bytes.\n",
- atari_dma_residual );
- #endif
- atari_scsi_fetch_restbytes();
- tt_scsi_dma.dma_ctrl = 0;
- }
-
- /* If the DMA is finished, fetch the rest bytes and turn it off */
- if (dma_stat & 0x40) {
- atari_dma_residual = 0;
- atari_scsi_fetch_restbytes();
- tt_scsi_dma.dma_ctrl = 0;
- }
-
- #endif /* REAL_DMA */
-
- /* If we got this interrupt, we don't need the other one any more */
- tt_mfp.int_pn_b = (unsigned char)~0x80;
-
- CHECK_ICNT("calling NCR5380_intr");
-
- save_flags(flags);
- NCR5380_intr( 0 );
- restore_flags(flags);
-
- #ifdef LOST_INTR
- CHECK_ICNT("returning, after NCR5380_intr");
- curr_intr_count = prev_intr_count;
- #endif
- }
-
-
- static void scsi_falcon_intr (struct intframe *fp, void *data)
-
- { int dma_stat;
- unsigned long flags;
- #ifdef LOST_INTR
- unsigned long prev_intr_count;
-
- prev_intr_count = curr_intr_count;
- curr_intr_count = intr_count;
- #endif
-
- #ifdef REAL_DMA
-
- /* Turn off DMA and select sector counter register before
- * accessing the status register (Atari recommendation!)
- */
- st_dma.dma_mode_status = 0x90;
- dma_stat = st_dma.dma_mode_status;
-
- /* Bit 0 indicates some error in the DMA process... don't know
- * what happened exactly (no further docu).
- */
- if (!(dma_stat & 0x01)) {
- /* DMA error */
- printk( "SCSI DMA error near 0x%08lx!\n", SCSI_DMA_GETADR() );
- }
-
- /* If the DMA was active, but now bit 1 is not clear, it is some
- * other 5380 interrupt that finishes the DMA transfer. We have to
- * calculate the number of residual bytes and give a warning if
- * bytes are stuck in the ST-DMA fifo (there's no way to reach them!)
- */
- if (atari_dma_active && (dma_stat & 0x02)) {
- unsigned long transferred;
-
- transferred = SCSI_DMA_GETADR() - atari_dma_startaddr;
- /* The ST-DMA address is incremented in 2-byte steps, but the
- * data are written only in 16-byte chunks. If the number of
- * transferred bytes is not divisible by 16, the remainder is
- * lost somewhere in outer space.
- */
- if (transferred & 15)
- printk( "SCSI DMA error: %ld bytes lost in ST-DMA fifo :-((\n",
- transferred & 15 );
-
- atari_dma_residual =
- ((struct NCR5380_hostdata *)(atari_scsi_host->hostdata))->dma_len -
- transferred;
- #if (NDEBUG & NDEBUG_DMA)
- printk( "SCSI DMA: There are %ld residual bytes.\n",
- atari_dma_residual );
- #endif
- }
- else
- atari_dma_residual = 0;
- atari_dma_active = 0;
-
- #endif /* REAL_DMA */
-
- CHECK_ICNT("calling NCR5380_intr");
-
- save_flags(flags);
- NCR5380_intr( 0 );
- restore_flags(flags);
-
- #ifdef LOST_INTR
- CHECK_ICNT("returning, after NCR5380_intr");
- curr_intr_count = prev_intr_count;
- #endif
- }
-
-
- static void atari_scsi_fetch_restbytes( void )
-
- { int nr;
- char *src, *dst;
-
- /* fetch rest bytes in the DMA register */
- dst = (char *)SCSI_DMA_READ_P( dma_addr_hi );
- if ((nr = ((long)dst & 3))) {
- /* there are 'nr' bytes left for the last long address before the
- DMA pointer */
- dst = (char *)( (unsigned long)dst & ~3 );
- #if (NDEBUG & NDEBUG_DMA)
- printk( "SCSI DMA: there are %d rest bytes for phys addr 0x%08lx",
- nr, (long)dst );
- #endif
- dst = (char *)PTOV(dst); /* The content of the DMA pointer
- * is a physical address! */
- #if (NDEBUG & NDEBUG_DMA)
- printk( " = virt addr 0x%08lx\n", (long)dst );
- #endif
- for( src = (char *)&tt_scsi_dma.dma_restdata; nr > 0; --nr )
- *dst++ = *src++;
- }
- }
-
-
- static int falcon_got_lock = 0;
- static struct wait_queue *falcon_fairness_wait = NULL;
- static int falcon_trying_lock = 0;
- static struct wait_queue *falcon_try_wait = NULL;
-
- /* This function releases the lock on the DMA chip if there is no
- * connected command and the disconnected queue is empty. On
- * releasing, instances of falcon_get_lock are awoken, that put
- * themselves to sleep for fairness. They can now try to get the lock
- * again (but others waiting longer more probably will win).
- */
-
- static void
- falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
-
- {
- if (IS_A_TT()) return;
-
- if (falcon_got_lock &&
- !hostdata->disconnected_queue &&
- !hostdata->issue_queue &&
- !hostdata->connected) {
-
- unsigned long oldflags;
-
- save_flags(oldflags);
- cli();
-
- falcon_got_lock = 0;
- stdma_release();
- wake_up( &falcon_fairness_wait );
-
- restore_flags(oldflags);
- }
- }
-
- /* This function manages the locking of the ST-DMA.
- * If the DMA isn't locked already for SCSI, it trys to lock it by
- * calling stdma_lock(). But if the DMA is locked by the SCSI code and
- * there are other drivers waiting for the chip, we do not issue the
- * command immediatly but wait on 'falcon_fairness_queue'. We will be
- * waked up when the DMA is unlocked by some SCSI interrupt. After that
- * we try to get the lock again.
- * But we must be prepared that more then one instance of
- * falcon_get_lock() is waiting on the fairness queue. They should not
- * try all at once to call stdma_lock(), one is enough! For that, the
- * first one sets 'falcon_trying_lock', others that see that variable
- * set wait on the queue 'falcon_try_wait'.
- * Complicated, complicated.... Sigh...
- */
-
- static void falcon_get_lock( void )
-
- {
- unsigned long oldflags;
-
- if (IS_A_TT()) return;
-
- save_flags(oldflags);
- cli();
-
- while( falcon_got_lock && stdma_others_waiting() )
- sleep_on( &falcon_fairness_wait );
-
- if (!falcon_got_lock) {
- if (!falcon_trying_lock) {
- falcon_trying_lock = 1;
- stdma_lock( scsi_falcon_intr, 0 );
- falcon_got_lock = 1;
- falcon_trying_lock = 0;
- wake_up( &falcon_try_wait );
- }
- else {
- sleep_on( &falcon_try_wait );
- }
- }
-
- restore_flags(oldflags);
- }
-
-
- /* This is the wrapper function for NCR5380_queue_command(). It just
- * trys to get the lock on the ST-DMA (see above) and then calls the
- * original function.
- */
-
- int atari_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
-
- {
- falcon_get_lock();
- return( NCR5380_queue_command( cmd, done ) );
- }
-
-
-
- int atari_scsi_detect (int hostno)
-
- { static int called = 0;
- struct Scsi_Host *instance;
-
- if (boot_info.machtype != MACH_ATARI || called)
- return( 0 );
-
- atari_scsi_reg_read = IS_A_TT() ? atari_scsi_tt_reg_read :
- atari_scsi_falcon_reg_read;
- atari_scsi_reg_write = IS_A_TT() ? atari_scsi_tt_reg_write :
- atari_scsi_falcon_reg_write;
-
- instance = scsi_register (hostno, sizeof (struct NCR5380_hostdata));
- atari_scsi_host = instance;
-
- NCR5380_init (instance);
- instance->irq = 0; /* not needed, but tested in NCR5380.c */
-
- if (IS_A_TT()) {
-
- add_isr( IRQ_TT_MFP_SCSI, scsi_tt_intr, 0, NULL);
- tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */
- tt_mfp.int_en_a |= 0x80; /* enabled */
- tt_mfp.int_mk_a |= 0x80; /* not masked */
- #ifdef REAL_DMA
- /* On the TT, we got a second interrupt for DMA ready and DMA buserror.
- * Since on DMA ready we get a "normal" interrupt, too, the service
- * routine for the second int just checks for buserrs.
- */
- add_isr( IRQ_TT_MFP_SCSIDMA, scsi_dma_buserr, 0, NULL);
- tt_mfp.active_edge &= ~0x20; /* DMA int on H->L */
- tt_mfp.int_en_b |= 0x80; /* enabled */
- tt_mfp.int_mk_b |= 0x80; /* not masked */
-
- tt_scsi_dma.dma_ctrl = 0;
- atari_dma_residual = 0;
- #endif /* REAL_DMA */
-
- }
- else { /* ! IS_A_TT */
-
- /* Nothing to do for the interrupt: the ST-DMA is initialized
- * already by atari_init_INTS()
- */
-
- #ifdef REAL_DMA
- atari_dma_residual = 0;
- atari_dma_active = 0;
- #endif
-
- /* Falcon's ST-DMA can work only in lower 16 MB, so
- * unchecked_isa_dma has to be set. But... the high level
- * codes allocates lots (!) of memory for buffers if this is
- * done. So the values for sg_tablesize and cmd_per_lun get
- * lowered a bit (you can leave this out if you have 16MB of
- * ST-Ram).
- */
- atari_scsi_host->unchecked_isa_dma =
- atari_scsi_host->hostt->unchecked_isa_dma = 1;
- #if I_HAVE_OVERRUNS == 3
- atari_scsi_host->sg_tablesize =
- atari_scsi_host->hostt->sg_tablesize = SG_NONE;
- #else
- atari_scsi_host->sg_tablesize =
- atari_scsi_host->hostt->sg_tablesize = 8;
- #endif
- atari_scsi_host->hostt->cmd_per_lun = 8;
- }
-
- printk( "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCATTERGATHER=%d",
- instance->host_no, instance->hostt->can_queue,
- instance->hostt->cmd_per_lun,
- instance->hostt->sg_tablesize );
- NCR5380_print_options (instance);
- printk ("\n");
-
- called = 1;
-
- return( 1 );
- }
-
- int atari_scsi_reset( Scsi_Cmnd *cmd )
-
- { int rv;
-
- /* For doing the reset, SCSI interrupts must be disabled first,
- * since the 5380 raises its IRQ line while _RST is active and we
- * can't disable interrupts completely, since we need the timer.
- */
-
- if (IS_A_TT())
- tt_mfp.int_en_a &= ~0x80;
- else
- mfp.int_en_b &= ~0x80;
-
- rv = NCR5380_reset( cmd );
-
- /* Re-enable ints and abort a maybe active DMA transfer */
- if (IS_A_TT()) {
- #ifdef REAL_DMA
- tt_scsi_dma.dma_ctrl = 0;
- #endif /* REAL_DMA */
- tt_mfp.int_en_a |= 0x80;
- }
- else {
- #ifdef REAL_DMA
- st_dma.dma_mode_status = 0x90;
- atari_dma_active = 0;
- #endif /* REAL_DMA */
- mfp.int_en_b |= 0x80;
- }
-
- return( rv );
- }
-
-
- const char * atari_scsi_info( void )
-
- { /* atari_scsi_detect() is verbose enough... */
- static const char string[] = "";
- return string;
- }
-
-
- #if defined(REAL_DMA) || defined(REAL_DMA_POLL) || defined(PSEUDO_DMA)
-
- unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
- unsigned long count, int dir )
- {
- unsigned long addr = VTOP( data ),
- cando = atari_dma_xfer_len( count );
-
- #if (NDEBUG & NDEBUG_DMA)
- printk ("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, cando = %ld, dir = %d\n",
- instance->host_no, data, addr, count, cando, dir);
- #endif
-
- atari_dma_startaddr = addr; /* Needed for calculating residual later. */
-
- if (dir)
- /* write: push any dirty cache out before sending it to the
- * peripheral. (Must be done before DMA setup, since at least the
- * ST-DMA begins to fill internal buffers right after setup.
- */
- cache_push( addr, cando );
- else
- /* read: invalidate any cache, may be altered after DMA without CPU
- * knowledge
- */
- cache_clear( addr, cando );
-
- if (cando == 0)
- printk( "SCSI warning: DMA programed for 0 bytes !\n" );
-
- if (IS_A_TT()) {
-
- tt_scsi_dma.dma_ctrl = dir;
- SCSI_DMA_WRITE_P( dma_addr_hi, addr );
- SCSI_DMA_WRITE_P( dma_cnt_hi, cando );
- tt_scsi_dma.dma_ctrl = dir | 2;
- }
- else { /* ! IS_A_TT */
-
- /* set address */
- SCSI_DMA_SETADR( addr );
-
- /* toggle direction bit to clear FIFO and set DMA direction */
- dir <<= 8;
- st_dma.dma_mode_status = 0x90 | dir;
- st_dma.dma_mode_status = 0x90 | (dir ^ 0x100);
- st_dma.dma_mode_status = 0x90 | dir;
- st_dma.fdc_acces_seccount = cando >> 9;
-
- st_dma.dma_mode_status = 0x10 | dir;
- /* need not restore value of dir, only boolean value is tested */
- atari_dma_active = 1;
- }
-
- return( cando );
- }
-
-
- static long atari_scsi_dma_residual( struct Scsi_Host *instance )
-
- {
- return( atari_dma_residual );
- }
-
- /* This function calculates the number of bytes that can be transferred
- * via DMA. On the TT, this is arbitrary, but on the Falcon we have to use
- * the ST-DMA chip. There are only multiples of 512 bytes possible and
- * max. 256*512 bytes :-( This means also, that defining READ_OVERRUNS is
- * not possible, since that would require to program the DMA for n*512 - 2
- * bytes.
- */
-
- static unsigned long atari_dma_xfer_len( unsigned long wanted_len )
-
- {
- unsigned long possible_len;
-
- if (IS_A_TT())
- /* TT SCSI DMA can transfer arbitrary #bytes */
- return( wanted_len );
-
- /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.
- * 255*512 bytes, but this should be enough)
- */
- possible_len =wanted_len & ~0x1ff;
- if (possible_len > 255*512)
- possible_len = 255*512;
-
- #if (NDEBUG & NDEBUG_DMA)
- if (possible_len != wanted_len)
- printk( "Sorry, must cut DMA transfer size to %ld bytes instead of %ld\n",
- possible_len, wanted_len );
- #endif
-
- return( possible_len );
- }
-
-
- #endif /* REAL_DMA || REAL_DMA_POLL || PSEUDO_DMA */
-
-
- /* NCR5380 register access functions
- *
- * There are seperate functions for TT and Falcon, because the access
- * methods are quite different. The calling macros NCR5380_read and
- * NCR5380_write call these functions via function pointers.
- */
-
- static unsigned char atari_scsi_tt_reg_read( unsigned char reg )
-
- {
- return( tt_scsi_regp[reg * 2] );
- }
-
- static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value )
-
- {
- tt_scsi_regp[reg * 2] = value;
- }
-
- static unsigned char atari_scsi_falcon_reg_read( unsigned char reg )
-
- {
- dma_wd.dma_mode_status= (u_short)(0x88 + reg);
- return( (u_char)dma_wd.fdc_acces_seccount );
- }
-
- static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value )
-
- {
- dma_wd.dma_mode_status = (u_short)(0x88 + reg);
- dma_wd.fdc_acces_seccount = (u_short)value;
- }
-
-
- #include "atari_NCR5380.c"
-
- #endif /* CONFIG_ATARI_*_SCSI */
-
-
-
-
-
-
-
-
-
-